package vn.edu.saigontech.ncms.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import vn.edu.saigontech.ncms.model.enumeration.Campus;
import vn.edu.saigontech.ncms.model.enumeration.Gender;
import vn.edu.saigontech.ncms.model.enumeration.Nationality;
import vn.edu.saigontech.ncms.model.enumeration.TeacherType;
import vn.edu.saigontech.ncms.model.info.Offering;
import vn.edu.saigontech.ncms.model.info.Teacher;
import vn.edu.saigontech.ncms.service.OfferingService;
import vn.edu.saigontech.ncms.service.TeacherService;
import vn.edu.saigontech.ncms.util.Checker;
import vn.edu.saigontech.ncms.util.DateUtil;

public class TeacherServiceImpl extends HibernateGenericService<Teacher, Long>
		implements TeacherService {

	@Override
	@SuppressWarnings("unchecked")
	public Collection<Teacher> findAll() {
		Criteria criteria = this.createCriteria().addOrder(
				Order.asc("firstName"));
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public Collection<Teacher> findAllAreActive() {
		Criteria criteria = this.createCriteria();
		criteria.add(Restrictions.eq("active", true));
		criteria.addOrder(Order.asc("firstName"));
		return criteria.list();
	}
	
	@SuppressWarnings("unchecked")
	public Collection<Teacher> findActiveByTeacherType(TeacherType teacherType) {
		Criteria criteria = this.createCriteria();
		criteria.add(Restrictions.eq("active", true));
		criteria.add(Restrictions.eq("teacherType", teacherType));
		criteria.addOrder(Order.asc("firstName"));
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public Collection<Teacher> find(String firstName, String midName, String lastName, Date dob,
			TeacherType teacherType, Gender gender, Nationality nationality, Campus campus,
			String email, String phoneNumber, Date fromDate, Date toDate, Boolean active, String comment) {
		Criteria criteria = this.createCriteria();
		if (!Checker.isEmpty(firstName)) {
			criteria.add(Restrictions.ilike("firstName", firstName, MatchMode.ANYWHERE));
		}
		if (!Checker.isEmpty(midName)) {
			criteria.add(Restrictions.ilike("midName", midName, MatchMode.ANYWHERE));
		}
		if (!Checker.isEmpty(lastName)) {
			criteria.add(Restrictions.ilike("lastName", lastName, MatchMode.ANYWHERE));
		}
		if(Checker.isNotNull(teacherType)) {
			criteria.add(Restrictions.eq("teacherType", teacherType));
		}
		if (!Checker.isNull(dob)) {
			criteria.add(Restrictions.eq("dateOfBirth", dob));
		}
		if (!Checker.isNull(gender)) {
			criteria.add(Restrictions.eq("gender", gender));
		}
		if (!Checker.isNull(nationality)) {
			criteria.add(Restrictions.eq("nationality", nationality));
		}
		if(!Checker.isNull(campus)) {
			criteria.add(Restrictions.eq("campus", campus));
		}
		if (!Checker.isEmpty(email)) {
			criteria.add(Restrictions.ilike("email", email, MatchMode.ANYWHERE));
		}
		if (!Checker.isEmpty(phoneNumber)) {
			criteria.add(Restrictions.ilike("phoneNumber", phoneNumber, MatchMode.ANYWHERE));
		}
		if (!Checker.isNull(active)) {
			criteria.add(Restrictions.eq("active", active));
		}
		if (!Checker.isEmpty(comment)) {
			criteria.add(Restrictions.ilike("comment", comment, MatchMode.ANYWHERE));
		}
		List<Teacher> teachers = criteria.list();
		List<Teacher> ret = new ArrayList<Teacher>();
		if(!Checker.isNull(fromDate) && !Checker.isNull(toDate)) {
			Collection<Offering> offerings = OfferingService.INSTANCE.findByDate(fromDate, toDate);
			for(Teacher teacher : teachers) {
				for(Offering offering : offerings) {
					if(offering.containsInstructor(teacher) & !ret.contains(teacher)) {
						ret.add(teacher);
						continue;
					}
				}
			}
		} else return teachers;
		return ret;
	}

	@Override
	public boolean deleteById(Long id) {
		if (OfferingService.INSTANCE.findByTeacherId(id).isEmpty()) {
			return super.deleteById(id);
		}
		return false;
	}

	@Override
	public Teacher find(Long offeringId, Date date) {
		Offering offering = OfferingService.INSTANCE.findById(offeringId);
		return offering.getInstructorOfDay(DateUtil.getDayOfWeek(date), date);
	}
}